//
//  BEViewControllerExtension.swift
//  BasicExtensions
//
//  Created by Fanxx on 2018/3/23.
//  Copyright © 2018年 fanxx. All rights reserved.
//


import UIKit


//extension UINavigationController: ECNamespaceWrappable {}
extension UIViewController {
    /// 显示状态
    @objc public enum AppearState: Int {
        /// 还未显示
        case notAppeare
        /// 显示中(viewWillAppear -> viewDidAppear)
        case appearing
        /// 已显示(viewDidAppear -> viewWillDisappear)
        case appeared
        /// 消失中(viewWillDisappear -> viewDidDisappear)
        case disappearing
        /// 已消失(viewDidDisappear -> viewWillAppear)
        case disappeared
        /// 是否显示中(viewWillAppear -> viewDidDisappear)
        public var isAppearing: Bool {
            return self.in(.appearing, .appeared, .disappearing)
        }
        /// 已显示(viewDidAppear -> viewWillDisappear)
        public var isAppeared: Bool {
            return self == .appeared
        }
    }
    /// 显示状态，可以kvo来执行hook, 要注意枚举类型在KVO的change里面会显示为nil，需要自己来取self.appearState
    @objc dynamic public var appearState: AppearState {
        get { return self.extend["basicExtensions.appearState"] ?? .notAppeare }
        set { self.extend["basicExtensions.appearState"] = newValue }
    }
    /// 第一次显示
    @objc dynamic public var isFirstAppearance: Bool {
        get { return self.extend["basicExtensions.isFirstAppearance"] ?? true }
        set { self.extend["basicExtensions.isFirstAppearance"] = newValue }
    }
    /// 视图正在重新布局
    @objc dynamic public var isViewLayingOut: Bool {
        get { return self.extend["basicExtensions.isViewLayingOut"] ?? false }
        set { self.extend["basicExtensions.isViewLayingOut"] = newValue }
    }
    internal class func __beHook() {
        UIViewController.swizzle(#selector(viewWillAppear(_:)), to: #selector(__beViewWillAppear(_:)))
        UIViewController.swizzle(#selector(viewDidAppear(_:)), to: #selector(__beViewDidAppear(_:)))
        UIViewController.swizzle(#selector(viewWillDisappear(_:)), to: #selector(__beViewWillDisappear(_:)))
        UIViewController.swizzle(#selector(viewDidDisappear(_:)), to: #selector(__beViewDidDisappear(_:)))
        UIViewController.swizzle(#selector(viewWillLayoutSubviews), to: #selector(__beViewWillLayoutSubviews))
        UIViewController.swizzle(#selector(viewDidLayoutSubviews), to: #selector(__beViewDidLayoutSubviews))
    }
    @objc func __beViewWillAppear(_ animated: Bool) {
        self.appearState = .appearing
        self.__beViewWillAppear(animated)
    }
    @objc func __beViewDidAppear(_ animated: Bool) {
        self.appearState = .appeared
        self.__beViewDidAppear(animated)
    }
    @objc func __beViewWillDisappear(_ animated: Bool) {
        self.appearState = .disappearing
        self.__beViewWillDisappear(animated)
    }
    @objc func __beViewDidDisappear(_ animated: Bool) {
        self.appearState = .disappeared
        self.__beViewDidDisappear(animated)
        if self.isFirstAppearance {
            self.isFirstAppearance = false
        }
    }
    @objc func __beViewWillLayoutSubviews() {
        self.isViewLayingOut = true
        self.__beViewWillLayoutSubviews()
    }
    @objc func __beViewDidLayoutSubviews() {
        self.__beViewDidLayoutSubviews()
        self.isViewLayingOut = false
    }
}
extension UIViewController {
    public static var current: UIViewController? {
        if var target = UIApplication.shared.delegate?.window??.rootViewController {
            repeat {
                if let c = target.__beUpLayerViewController() {
                    target = c
                }else{
                    break
                }
            } while (true)
            return target
        }
        return nil
    }
    ///获取上一层Controller
    private func __beUpLayerViewController() -> UIViewController? {
        if let target = self.presentedViewController {
            return target
        }
        if let tb = self as? UITabBarController, let target = tb.selectedViewController {
            return target
        }
        if let nv = self as? UINavigationController, let target = nv.topViewController {
            return target
        }
        return nil
    }
}
extension UINavigationController {
    /// 若存在该Controller则退回该Controller，否则创建新的
    /// - parameter creation: 不存在时的创建函数
    /// - parameter config: 在打开前可在此做配置，不管是已经存在还是新创建都会调用此方法
    @discardableResult
    public func popOrPush<T: UIViewController>(for viewControllerType:T.Type, creation:(() -> T)? = nil, config: ((T) -> Void)? = nil, animated: Bool = true) -> [UIViewController]? {
        if let controller = self.viewControllers.last(where: { $0 is T }) as? T {
            config?(controller)
            return self.popToViewController(controller, animated: animated)
        }
        let controller = creation?() ?? T()
        config?(controller)
        self.pushViewController(controller, animated: animated)
        
        return self.viewControllers
    }
    /// 若存在该Controller则退回该Controller，否则创建新的并替换当前的
    /// - parameter creation: 不存在时的创建函数
    /// - parameter config: 在打开前可在此做配置，不管是已经存在还是新创建都会调用此方法
    @discardableResult
    public func popOrReplace<T: UIViewController>(for viewControllerType:T.Type, creation:(() -> T)? = nil, config: ((T) -> Void)? = nil, animated: Bool = true) -> [UIViewController]? {
        if let controller = self.viewControllers.last(where: { $0 is T }) as? T {
            config?(controller)
            return self.popToViewController(controller, animated: animated)
        }
        let controller = creation?() ?? T()
        config?(controller)
        self.replace(controller, animated: animated)
        
        return self.viewControllers
    }
    /// 推出指定数量的Controller，默认1
    public func pop(_ count:Int = 1, animated: Bool = true) {
        if count < 2 {
            self.popViewController(animated: animated)
        }else if self.viewControllers.count - 1 > count {
            let target = self.viewControllers[self.viewControllers.count - 1 - count]
            self.popToViewController(target, animated: animated)
        }else{
            self.popToRootViewController(animated: animated)
        }
    }
    /// 推入多个Controller
    public func push(_ viewControllers:[UIViewController], animated: Bool) {
        var cs = self.viewControllers
        cs.append(contentsOf: viewControllers)
        self.setViewControllers(cs, animated: animated)
    }
    /// 替换指定数量的Controller为指定的Controller
    /// - parameter count: 默认为1，替换掉最后一个，多个则往前数
    public func replace(_ viewController:UIViewController, count: Int = 1, animated: Bool = true) {
        var controllers = self.viewControllers
        controllers.removeLast(count)
        controllers.append(viewController)
        self.setViewControllers(controllers, animated: animated)
    }
    /// 替换前一个Controller为后一个Controller
    /// - parameter count: 默认为nil，替换后会将该Controller后面的Controller全部推出，1则代表只推出要替换的Controller，再大则往后数，0则表现为插入到前面不替换
    public func replace(_ source: UIViewController.Type, to target: UIViewController, count: Int? = nil, animated: Bool = true) {
        var controllers = self.viewControllers
        if let index = controllers.lastIndex(where: { $0.isKind(of: source)}) {
            if let count = count, index + count < controllers.count {
                controllers.removeSubrange(index..<index + count)
                controllers.insert(target, at: index)
            }else{
                controllers.removeLast(controllers.count - index)
                controllers.append(target)
            }
            self.setViewControllers(controllers, animated: animated)
        }
    }
    public func insert(_ viewController:UIViewController, at index: Int) {
        var controllers = self.viewControllers
        controllers.insert(viewController, at: index)
        self.setViewControllers(controllers, animated: false)
    }
    public func insert(_ viewController:UIViewController, before refController: UIViewController.Type) {
        var controllers = self.viewControllers
        if let index = controllers.lastIndex(where: { $0.isKind(of: refController)}) {
            controllers.insert(viewController, at: index)
            self.setViewControllers(controllers, animated: false)
        }
    }
    public func insert(_ viewController:UIViewController, after refController: UIViewController.Type) {
        var controllers = self.viewControllers
        if let index = controllers.lastIndex(where: { $0.isKind(of: refController)}) {
            if index == controllers.count - 1 {
                controllers.append(viewController)
            }else{
                controllers.insert(viewController, at: index + 1)
            }
            self.setViewControllers(controllers, animated: false)
        }
    }
}
